home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / upc12bs1.zip / UUCICO / modem.c < prev    next >
C/C++ Source or Header  |  1993-10-03  |  37KB  |  1,008 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    m o d e m . c                                                   */
  3. /*                                                                    */
  4. /*    High level modem control routines for UUPC/extended             */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*       Changes Copyright (c) 1989-1993 by Kendra Electronic         */
  9. /*       Wonderworks.                                                 */
  10. /*                                                                    */
  11. /*       All rights reserved except those explicitly granted by       */
  12. /*       the UUPC/extended license agreement.                         */
  13. /*--------------------------------------------------------------------*/
  14.  
  15. /*--------------------------------------------------------------------*/
  16. /*                          RCS Information                           */
  17. /*--------------------------------------------------------------------*/
  18.  
  19. /*
  20.  *    $Id: modem.c 1.31 1993/10/03 22:34:33 ahd Exp $
  21.  *
  22.  *    Revision history:
  23.  *    $Log: modem.c $
  24.  * Revision 1.31  1993/10/03  22:34:33  ahd
  25.  * Insure priority values are reset when loading modem information
  26.  *
  27.  * Revision 1.30  1993/10/03  20:43:08  ahd
  28.  * Move slowWrite to script.c
  29.  *
  30.  * Revision 1.29  1993/10/01  01:17:44  ahd
  31.  * Use atol() for reading port speed
  32.  *
  33.  * Revision 1.28  1993/09/29  13:18:06  ahd
  34.  * Clear raise before calling script processor in shutDown
  35.  *
  36.  * Revision 1.28  1993/09/29  13:18:06  ahd
  37.  * Clear raise before calling script processor in shutDown
  38.  *
  39.  * Revision 1.27  1993/09/29  05:25:21  ahd
  40.  * Correct resetting of raised flag
  41.  *
  42.  * Revision 1.26  1993/09/29  04:49:20  ahd
  43.  * Allow unique signal handler for suspend port processing
  44.  *
  45.  * Revision 1.25  1993/09/28  01:38:19  ahd
  46.  * Add configurable timeout for conversation start up phase
  47.  *
  48.  * Revision 1.24  1993/09/27  04:04:06  ahd
  49.  * Normalize references to modem speed to avoid incorrect displays
  50.  *
  51.  * Revision 1.23  1993/09/27  00:45:20  ahd
  52.  * Add suspend of serial port processing from K. Rommel
  53.  *
  54.  * Revision 1.22  1993/09/25  03:07:56  ahd
  55.  * Invoke set priority functions
  56.  *
  57.  * Revision 1.21  1993/09/23  03:26:51  ahd
  58.  * Never try to autobaud a network connection
  59.  *
  60.  * Revision 1.20  1993/09/20  04:46:34  ahd
  61.  * OS/2 2.x support (BC++ 1.0 support)
  62.  * TCP/IP support from Dave Watt
  63.  * 't' protocol support
  64.  *
  65.  * Revision 1.19  1993/08/03  03:11:49  ahd
  66.  * Add Description= line
  67.  *
  68.  * Revision 1.18  1993/07/13  01:13:32  ahd
  69.  * Correct message for systems waiting forever
  70.  *
  71.  * Revision 1.17  1993/07/05  14:47:05  ahd
  72.  * Drop obsolete  tag from "variablepacket"
  73.  * Set default timeout of 30 seconds for answer timeout
  74.  *
  75.  * Revision 1.16  1993/06/16  04:03:25  ahd
  76.  * Lower max wait time for NT
  77.  *
  78.  * Revision 1.15  1993/05/30  15:25:50  ahd
  79.  * Multiple driver support
  80.  *
  81.  * Revision 1.14  1993/05/30  00:04:53  ahd
  82.  * Multiple communications drivers support
  83.  *
  84.  * Revision 1.13  1993/04/15  03:21:06  ahd
  85.  * Add CD() call to hot login procedure
  86.  *
  87.  * Revision 1.12  1993/04/11  00:34:11  ahd
  88.  * Global edits for year, TEXT, etc.
  89.  *
  90.  * Revision 1.11  1993/04/05  04:35:40  ahd
  91.  * Set clear abort processing flag (norecover) from ulib.c
  92.  *
  93.  * Revision 1.10  1993/03/06  23:04:54  ahd
  94.  * make modem connected messages consistent
  95.  *
  96.  * Revision 1.9  1993/01/23  19:08:09  ahd
  97.  * Add additional shutDown() commands even when modem does not init
  98.  *
  99.  * Revision 1.8  1992/12/30  13:11:44  dmwatt
  100.  * Check for NULL brand pointer before comparing
  101.  *
  102.  * Revision 1.7  1992/12/18  12:05:57  ahd
  103.  * Flag variable packet as obsolete
  104.  *
  105.  * Revision 1.6  1992/11/28  19:51:16  ahd
  106.  * Add program exit time to waiting for callin message
  107.  * Make time parameter to callin() const
  108.  *
  109.  * Revision 1.5  1992/11/22  21:20:45  ahd
  110.  * Use strpool for const string allocation
  111.  *
  112.  * Revision 1.4  1992/11/19  03:01:21  ahd
  113.  * drop rcsid
  114.  *
  115.  * Revision 1.3  1992/11/18  03:48:24  ahd
  116.  * Move check of call window to avoid premature lock file overhead
  117.  *
  118.  * Revision 1.2  1992/11/15  20:12:17  ahd
  119.  * Clean up modem file support for different protocols
  120.  *
  121.  * Revision 1.1  1992/11/12  12:32:18  ahd
  122.  * Initial revision
  123.  *
  124.  */
  125.  
  126. /*--------------------------------------------------------------------*/
  127. /*                        System include files                        */
  128. /*--------------------------------------------------------------------*/
  129.  
  130. #include <limits.h>
  131. #include <stdio.h>
  132. #include <stdlib.h>
  133. #include <string.h>
  134. #include <ctype.h>
  135. #include <time.h>
  136. #include <limits.h>
  137. #include <sys/types.h>
  138.  
  139. /*--------------------------------------------------------------------*/
  140. /*                    UUPC/extended include files                     */
  141. /*--------------------------------------------------------------------*/
  142.  
  143. #include "lib.h"
  144. #include "hostable.h"
  145. #include "arpadate.h"
  146. #include "catcher.h"
  147. #include "checktim.h"
  148. #include "commlib.h"
  149. #include "dater.h"
  150. #include "dcp.h"
  151. #include "dcpsys.h"
  152. #include "hlib.h"
  153. #include "modem.h"
  154. #include "script.h"
  155. #include "security.h"
  156. #include "ssleep.h"
  157. #include "suspend.h"
  158. #include "usrcatch.h"
  159.  
  160. /*--------------------------------------------------------------------*/
  161. /*                          Global variables                          */
  162. /*--------------------------------------------------------------------*/
  163.  
  164. char *M_device = NULL;          /*Public to show in login banner     */
  165.  
  166. static char **answer, **initialize, **dropline, **ring, **connect;
  167. static char **noconnect;
  168. static char *dialPrefix, *dialSuffix;
  169. static char *M_suite;
  170. static char *dummy;
  171.  
  172. static KEWSHORT dialTimeout, modemTimeout, scriptTimeout;
  173. static KEWSHORT answerTimeout;
  174. static BPS inspeed;
  175. static KEWSHORT gWindowSize, gPacketSize;
  176. static KEWSHORT vWindowSize, vPacketSize;
  177. static KEWSHORT GWindowSize, GPacketSize;
  178.  
  179. KEWSHORT M_charDelay;
  180. KEWSHORT M_fPacketSize;
  181. KEWSHORT M_gPacketTimeout;       /* "g" procotol                  */
  182. KEWSHORT M_fPacketTimeout;       /* "f" procotol                  */
  183. KEWSHORT M_tPacketTimeout;       /* "t" procotol                  */
  184. KEWSHORT M_startupTimeout;       /* pre-procotol exchanges        */
  185. KEWSHORT M_MaxErr= 10;        /* Allowed errors per single packet    */
  186. KEWSHORT M_MaxErr;            /* Allowed errors per single packet    */
  187. KEWSHORT M_xfer_bufsize;      /* Buffering used for file transfers */
  188. static KEWSHORT M_priority = 999;
  189. static KEWSHORT M_prioritydelta = 999;
  190.  
  191. boolean bmodemflag[MODEM_LAST];
  192.  
  193. static FLAGTABLE modemFlags[] = {
  194.    { "carrierdetect",  MODEM_CD,          B_LOCAL },
  195.    { "direct",         MODEM_DIRECT,      B_LOCAL },
  196.    { "fixedspeed",     MODEM_FIXEDSPEED,  B_LOCAL },
  197.    { "variablepacket", MODEM_VARIABLEPACKET, B_LOCAL },
  198.    { "largepacket",    MODEM_LARGEPACKET, B_LOCAL | B_OBSOLETE },
  199.    { nil(char) }
  200. }           ;
  201.  
  202. static CONFIGTABLE modemtable[] = {
  203.    { "answer",        (char **) &answer,       B_LIST   | B_UUCICO },
  204.    { "answertimeout", (char **) &answerTimeout,B_SHORT| B_UUCICO },
  205.    { "biggpacketsize",(char **) &GPacketSize,  B_SHORT| B_UUCICO },
  206.    { "biggwindowsize",(char **) &GWindowSize,  B_SHORT| B_UUCICO },
  207.    { "chardelay",     (char **) &M_charDelay,  B_SHORT| B_UUCICO },
  208.    { "connect",       (char **) &connect,      B_LIST   | B_UUCICO },
  209.    { "description",   &dummy,                  B_TOKEN  },
  210.    { "device",        &M_device,               B_TOKEN| B_UUCICO | B_REQUIRED },
  211.    { "dialprefix",    &dialPrefix,B_STRING | B_UUCICO | B_REQUIRED },
  212.    { "dialsuffix",    &dialSuffix,             B_STRING | B_UUCICO },
  213.    { "dialtimeout",   (char **) &dialTimeout,  B_SHORT| B_UUCICO },
  214.    { "fpacketsize",   (char **) &M_fPacketSize,B_SHORT| B_UUCICO },
  215.    { "fpackettimeout",(char **) &M_fPacketTimeout, B_SHORT | B_UUCICO },
  216.    { "gpacketsize",   (char **) &gPacketSize,  B_SHORT| B_UUCICO },
  217.    { "gpackettimeout",(char **) &M_gPacketTimeout, B_SHORT | B_UUCICO },
  218.    { "gwindowsize",   (char **) &gWindowSize,  B_SHORT| B_UUCICO },
  219.    { "hangup",        (char **) &dropline,     B_LIST   | B_UUCICO },
  220.    { "initialize",    (char **) &initialize,   B_LIST   | B_UUCICO },
  221.    { "inspeed",       (char **) &inspeed,      B_LONG   | B_UUCICO },
  222.    { "maximumerrors", (char **) &M_MaxErr,     B_SHORT| B_UUCICO },
  223.    { "modemtimeout",  (char **) &modemTimeout, B_SHORT| B_UUCICO },
  224.    { "noconnect",     (char **) &noconnect,    B_LIST   | B_UUCICO },
  225.    { "options",       (char **) bmodemflag,    B_ALL    | B_BOOLEAN},
  226.    { "porttimeout",   NULL,                    B_OBSOLETE },
  227.    {"priority",       (char **) &M_priority,     B_SHORT |B_UUCICO},
  228.    {"prioritydelta",  (char **) &M_prioritydelta,B_SHORT |B_UUCICO},
  229.    { "ring",          (char **) &ring,         B_LIST   | B_UUCICO },
  230.    { "scripttimeout", (char **) &scriptTimeout,B_SHORT| B_UUCICO },
  231.    { "startuptimeout",(char **) &M_startupTimeout, B_SHORT | B_UUCICO },
  232.    { "suite",         &M_suite,                B_TOKEN  | B_UUCICO },
  233.    { "transferbuffer",(char **) &M_xfer_bufsize, B_SHORT| B_UUCICO },
  234.    { "tpackettimeout",(char **) &M_tPacketTimeout, B_SHORT | B_UUCICO },
  235.    { "vpacketsize",   (char **) &vPacketSize,  B_SHORT| B_UUCICO },
  236.    { "vwindowsize",   (char **) &vWindowSize,  B_SHORT| B_UUCICO },
  237.    { nil(char) }
  238. }; /* modemtable */
  239.  
  240. /*--------------------------------------------------------------------*/
  241. /*                    Internal function prototypes                    */
  242. /*--------------------------------------------------------------------*/
  243.  
  244. static boolean dial(char *number, const BPS speed);
  245.  
  246. static boolean sendlist( char **list, int timeout, int lasttimeout,
  247.                          char **failure);
  248.  
  249. static boolean sendalt( char *string, int timeout, char **failure);
  250.  
  251. static void autobaud( const BPS speed);
  252.  
  253. /*--------------------------------------------------------------------*/
  254. /*              Define current file name for references               */
  255. /*--------------------------------------------------------------------*/
  256.  
  257. currentfile();
  258.  
  259. /*--------------------------------------------------------------------*/
  260. /*    c a l l u p                                                     */
  261. /*                                                                    */
  262. /*    script processor - nothing fancy!                               */
  263. /*--------------------------------------------------------------------*/
  264.  
  265. CONN_STATE callup( void )
  266. {
  267.    char *exp;
  268.    int i;
  269.    BPS speed;
  270.  
  271. /*--------------------------------------------------------------------*/
  272. /*             Announce we are trying to call the system              */
  273. /*--------------------------------------------------------------------*/
  274.  
  275.    printmsg(1, "callup: Calling %s via %s at %s on %s",
  276.           rmtname, flds[FLD_TYPE], flds[FLD_SPEED], arpadate());
  277.  
  278.    speed = (BPS) atol( flds[FLD_SPEED] );
  279.    if (speed < 300)
  280.    {
  281.       printmsg(0,"callup: Modem speed %s is invalid.",
  282.                   flds[FLD_SPEED]);
  283.       hostp->hstatus = invalid_device;
  284.       return CONN_INITIALIZE;
  285.    }
  286.  
  287. /*--------------------------------------------------------------------*/
  288. /*                         Dial the telephone                         */
  289. /*--------------------------------------------------------------------*/
  290.  
  291.    if (! dial(flds[FLD_PHONE],speed))
  292.       return CONN_DROPLINE;
  293.  
  294. /*--------------------------------------------------------------------*/
  295. /*             The modem is connected; now login the host             */
  296. /*--------------------------------------------------------------------*/
  297.  
  298.    for (i = FLD_EXPECT; i < kflds; i += 2)
  299.    {
  300.  
  301.       exp = flds[i];
  302.       printmsg(2, "expecting %d of %d \"%s\"", i, kflds, exp);
  303.       if (!sendalt( exp, scriptTimeout , noconnect))
  304.       {
  305.          printmsg(0, "SCRIPT FAILED");
  306.          hostp->hstatus =  script_failed;
  307.          return CONN_DROPLINE;
  308.       } /* if */
  309.  
  310.       printmsg(2, "callup: sending %d of %d \"%s\"",
  311.                    i + 1, kflds, flds[i + 1]);
  312.       sendstr(flds[i + 1]);
  313.  
  314.    } /*for*/
  315.  
  316.    return CONN_PROTOCOL;
  317.  
  318. } /*callup*/
  319.  
  320. /*--------------------------------------------------------------------*/
  321. /*    c a l l h o t                                                   */
  322. /*                                                                    */
  323. /*    Initialize processing when phone is already off the hook        */
  324. /*--------------------------------------------------------------------*/
  325.  
  326. CONN_STATE callhot( const BPS xspeed )
  327. {
  328.    BPS speed;
  329.  
  330. /*--------------------------------------------------------------------*/
  331. /*                        Open the serial port                        */
  332. /*--------------------------------------------------------------------*/
  333.  
  334.    if (E_inmodem == NULL)
  335.    {
  336.       printmsg(0,"callin: No modem name supplied for incoming calls!");
  337.       panic();
  338.    } /* if */
  339.  
  340. /*--------------------------------------------------------------------*/
  341. /*                        Set the modem speed                         */
  342. /*--------------------------------------------------------------------*/
  343.  
  344.    if ( xspeed == 0)
  345.       speed = inspeed;
  346.    else
  347.       speed = xspeed;
  348.  
  349. /*--------------------------------------------------------------------*/
  350. /*                    Open the communications port                    */
  351. /*--------------------------------------------------------------------*/
  352.  
  353.    norecovery = FALSE;           // Shutdown gracefully as needed
  354.    if (activeopenline(M_device, speed, bmodemflag[MODEM_DIRECT] ))
  355.       panic();
  356.  
  357. /*--------------------------------------------------------------------*/
  358. /*                          Initialize stats                          */
  359. /*--------------------------------------------------------------------*/
  360.  
  361.    memset( &remote_stats, 0, sizeof remote_stats);
  362.                               /* Clear remote stats for login        */
  363.    time(&remote_stats.ltime); /* Remember time of last attempt conn  */
  364.    remote_stats.calls ++ ;
  365.  
  366.    if (bmodemflag[MODEM_CD])
  367.       CD();                   /* Set the carrier detect flags        */
  368.  
  369.    return CONN_HOTLOGIN;
  370.  
  371. } /* callhot */
  372.  
  373. /*--------------------------------------------------------------------*/
  374. /*    c a l l i n                                                     */
  375. /*                                                                    */
  376. /*    Answer the modem in passive mode                                */
  377. /*--------------------------------------------------------------------*/
  378.  
  379. CONN_STATE callin( const time_t exit_time )
  380. {
  381.    char c;                    /* A character for input buffer        */
  382.  
  383.    int    offset;             /* Time to wait for telephone          */
  384.    time_t left;
  385.  
  386. /*--------------------------------------------------------------------*/
  387. /*    Determine how long we can wait for the telephone, up to         */
  388. /*    SHRT_MAX seconds.  Aside from Turbo C limits, this insures we   */
  389. /*    kick the modem once in a while.                                 */
  390. /*--------------------------------------------------------------------*/
  391.  
  392.       left =  exit_time - time(NULL);
  393.       if ( left < 0 )               /* Any time left?                */
  394.          return CONN_EXIT;             /* No --> shutdown            */
  395.  
  396.       if ( left > SHRT_MAX)
  397.          offset = SHRT_MAX;
  398.       else
  399.          offset = (int) left;
  400.  
  401. /*--------------------------------------------------------------------*/
  402. /*                        Open the serial port                        */
  403. /*--------------------------------------------------------------------*/
  404.  
  405.    if (E_inmodem == NULL)
  406.    {
  407.       printmsg(0,"callin: No modem name supplied for incoming calls!");
  408.       panic();
  409.    } /* if */
  410.  
  411. /*--------------------------------------------------------------------*/
  412. /*                    Open the communications port                    */
  413. /*--------------------------------------------------------------------*/
  414.  
  415.    norecovery = FALSE;           // Shutdown gracefully as needed
  416.  
  417. /*--------------------------------------------------------------------*/
  418. /*              Flush the input buffer of any characters              */
  419. /*--------------------------------------------------------------------*/
  420.  
  421.    if ( IsNetwork() )
  422.    {
  423.       if (passiveopenline(M_device, inspeed, bmodemflag[MODEM_DIRECT]))
  424.          panic();
  425.    }
  426.    else {
  427.       if (((ring == NULL) || (inspeed == 0)))
  428.       {
  429.          printmsg(0,"callin: Missing inspeed and/or ring values in modem "
  430.                     "configuration file.");
  431.          panic();
  432.       } /* if */
  433.  
  434.       if (passiveopenline(M_device, inspeed, bmodemflag[MODEM_DIRECT]))
  435.          panic();
  436.  
  437.       while (sread(&c ,1,0)); /* Discard trailing trash from modem
  438.                                  connect message                     */
  439.  
  440. /*--------------------------------------------------------------------*/
  441. /*                        Initialize the modem                        */
  442. /*--------------------------------------------------------------------*/
  443.  
  444.       if (!sendlist( initialize, modemTimeout, modemTimeout, NULL))
  445.       {
  446.          printmsg(0,"callin: Modem failed to initialize");
  447.          shutDown();
  448.          panic();
  449.       }
  450.  
  451.    } /* else */
  452.  
  453. /*--------------------------------------------------------------------*/
  454. /*                   Wait for the telephone to ring                   */
  455. /*--------------------------------------------------------------------*/
  456.  
  457.    printmsg(1,"Monitoring port %s device %s"
  458.                      " for %d minutes until %s",
  459.                      M_device, E_inmodem , (int) (offset / 60),
  460.                      (left > hhmm2sec(10000)) ?
  461.                               "user hits Ctrl-Break" :
  462.                               dater( exit_time , NULL));
  463.  
  464.    interactive_processing = FALSE;
  465.  
  466.    if (IsNetwork())
  467.    {                          /* Network connect is different        */
  468.       if (!WaitForNetConnect(offset))
  469.       {
  470.          interactive_processing = TRUE;
  471.          shutDown();
  472.          if ( suspend_processing )        // Give up modem for another process?
  473.          {
  474.            return CONN_WAIT;
  475.          }
  476.          return CONN_INITIALIZE;
  477.       }
  478.  
  479.       interactive_processing = TRUE;
  480.       printmsg(14, "callin: Modem reports connected");
  481.  
  482.    }
  483.    else {
  484.       if (!sendlist( ring,modemTimeout, offset, noconnect))
  485.       {                          /* Did it ring?                        */
  486.          interactive_processing = TRUE;
  487.          raised = 0;
  488.          shutDown();
  489.          if ( suspend_processing )        // Give up modem for another process?
  490.             return CONN_WAIT;
  491.          else
  492.             return CONN_INITIALIZE;     /* No --> Return to caller       */
  493.       }
  494.  
  495.       interactive_processing = TRUE;
  496.  
  497.       setPrty(M_priority, M_prioritydelta );
  498.                               // Into warp drive for actual transfers
  499.  
  500.       if(!sendlist(answer, modemTimeout,answerTimeout, noconnect))
  501.       {                           /* Pick up the telephone               */
  502.          printmsg(1,"callin: Modem failed to connect to incoming call");
  503.          shutDown();
  504.          return CONN_INITIALIZE;
  505.       }
  506.  
  507.       printmsg(14, "callin: Modem reports connected");
  508.  
  509.       autobaud(inspeed);      /* autobaud the modem                  */
  510.  
  511. /*--------------------------------------------------------------------*/
  512. /*        Flush the input buffer of any other input characters        */
  513. /*--------------------------------------------------------------------*/
  514.  
  515.       while (sread(&c ,1,0)); /* Discard trailing trash from modem
  516.                                  connect message                     */
  517.  
  518.    } /* else */
  519.  
  520.    memset( &remote_stats, 0, sizeof remote_stats);
  521.                               /* Clear remote stats for login        */
  522.  
  523.    time(&remote_stats.ltime); /* Remember time of last attempt conn  */
  524.    remote_stats.calls ++ ;
  525.  
  526.  
  527.    return CONN_LOGIN;
  528.  
  529. } /* callin */
  530.  
  531. /*--------------------------------------------------------------------*/
  532. /*    g e t m o d e m                                                 */
  533. /*                                                                    */
  534. /*    Read a modem configuration file                                 */
  535. /*--------------------------------------------------------------------*/
  536.  
  537. boolean getmodem( const char *brand)
  538. {
  539.    char filename[FILENAME_MAX];
  540.    static char *modem = NULL;
  541.    FILE *fp;
  542.    CONFIGTABLE *tptr;
  543.    size_t subscript;
  544.    boolean success;
  545.  
  546. /*--------------------------------------------------------------------*/
  547. /*                      Validate the modem name                       */
  548. /*   Added check for validity of modem ptr -- makes NT happier - dmw  */
  549. /*--------------------------------------------------------------------*/
  550.  
  551.    if ((modem != NULL) && equal(modem, brand)) /* Already initialized?*/
  552.       return TRUE;            /* Yes --> Don't process it again      */
  553.  
  554. /*--------------------------------------------------------------------*/
  555. /*                        Initialize the table                        */
  556. /*--------------------------------------------------------------------*/
  557.  
  558.    for (tptr = modemtable; tptr->sym != nil(char); tptr++)
  559.       if (tptr->bits & (B_TOKEN | B_STRING | B_LIST | B_CLIST))
  560.          *(tptr->loc) = nil(char);
  561.  
  562.    for (subscript = 0; subscript < MODEM_LAST; subscript++)
  563.       bmodemflag[subscript] = FALSE;
  564.  
  565.    M_charDelay = 00;          /* Default is no delay between chars    */
  566.    dialTimeout = 40;          /* Default is 40 seconds to dial phone  */
  567.    gPacketSize = SMALL_PACKET;
  568.    vPacketSize = MAXPACK;
  569.    GPacketSize = MAXPACK;
  570.    gWindowSize = 0;
  571.    vWindowSize = 0;
  572.    GWindowSize = 0;
  573.    M_fPacketSize = MAXPACK;
  574.    M_fPacketTimeout = 20;
  575.    M_gPacketTimeout = 10;
  576.    M_tPacketTimeout = 60;
  577.    modemTimeout  = 3;         /* Default is 3 seconds for modem cmds  */
  578.    scriptTimeout = 30;        /* Default is 30 seconds for script data*/
  579.    answerTimeout = 30;        /* Default is 30 seconds to answer phone*/
  580.    M_xfer_bufsize = BUFSIZ;   /* Buffering used for file transfers    */
  581.    M_MaxErr= 10;              /* Allowed errors per single packet     */
  582.    M_suite = NULL;            // Use default suite for communications
  583.    M_startupTimeout = 40;     // 40 seconds per message to exchange protocols
  584.  
  585.    M_priority = 999;
  586.    M_prioritydelta = 999;
  587.  
  588. /*--------------------------------------------------------------------*/
  589. /*                 Open the modem configuration file                  */
  590. /*--------------------------------------------------------------------*/
  591.  
  592.    if (equaln(brand,"COM",3))
  593.    {
  594.       printmsg(0,"Modem type %s is invalid; Snuffles suspects "
  595.                "your %s file is obsolete.", brand, E_systems);
  596.       panic();
  597.    }
  598.  
  599.    sprintf(filename,"%s/%s.MDM",E_confdir, brand);
  600.    if ((fp = FOPEN(filename, "r",TEXT_MODE)) == nil(FILE))
  601.    {
  602.       printmsg(0,"getmodem: Unable to locate configuration for %s",
  603.                brand);
  604.       printerr( filename );
  605.       return FALSE;
  606.    }
  607.  
  608. /*--------------------------------------------------------------------*/
  609. /*                We got the file open, now process it                */
  610. /*--------------------------------------------------------------------*/
  611.  
  612.    printmsg(3,"getmodem: loading modem configuration file %s", filename);
  613.    success = getconfig(fp, MODEM_CONFIG, B_UUCICO, modemtable, modemFlags);
  614.    fclose(fp);
  615.    if (!success)
  616.       return FALSE;
  617.  
  618. /*--------------------------------------------------------------------*/
  619. /*         Verify all required modem parameters were supplied         */
  620. /*--------------------------------------------------------------------*/
  621.  
  622.    success = TRUE;
  623.    for (tptr = modemtable; tptr->sym != nil(char); tptr++) {
  624.       if ((tptr->bits & (B_REQUIRED | B_FOUND)) == B_REQUIRED)
  625.       {
  626.          printmsg(0, "getmodem: configuration parameter \"%s\" must be set.",
  627.             tptr->sym);
  628.          success = FALSE;
  629.       } /* if */
  630.    } /* for */
  631.  
  632.    if ( ! success )           // Missing any required inputs?
  633.       return success;         // Yes --> Return failure to caller
  634.  
  635. /*--------------------------------------------------------------------*/
  636. /*       The strings are valid, try to initialize the pointers to     */
  637. /*       the processing routines.                                     */
  638. /*--------------------------------------------------------------------*/
  639.  
  640.    if ( ! chooseCommunications( M_suite ))
  641.       return FALSE;
  642.  
  643. /*--------------------------------------------------------------------*/
  644. /*       We have success, save modem name for next time to speed      */
  645. /*       initialize.                                                  */
  646. /*--------------------------------------------------------------------*/
  647.  
  648.    modem = newstr(brand);  /* Yes --> Remember it for next time   */
  649.  
  650.    return TRUE;
  651.  
  652. } /* getmodem */
  653.  
  654. /*--------------------------------------------------------------------*/
  655. /*    d i a l                                                         */
  656. /*                                                                    */
  657. /*    Generic modem dialer; only major limitation is that autoabaud   */
  658. /*    strings are not configurable                                    */
  659. /*--------------------------------------------------------------------*/
  660.  
  661. static boolean dial(char *number, const BPS speed)
  662. {
  663.    char buf[81];
  664.  
  665. /*--------------------------------------------------------------------*/
  666. /*                        Open the serial port                        */
  667. /*--------------------------------------------------------------------*/
  668.  
  669.    norecovery = FALSE;           // Shutdown gracefully as needed
  670.  
  671. /*--------------------------------------------------------------------*/
  672. /*              Flush the input buffer of any characters              */
  673. /*--------------------------------------------------------------------*/
  674.  
  675.    if ( IsNetwork() )
  676.    {
  677.       if (activeopenline(number, speed, bmodemflag[MODEM_DIRECT]))
  678.       {
  679.          hostp->hstatus =  nodevice;
  680.          return FALSE;
  681.       }
  682.    }
  683.    else {
  684.  
  685.       if (activeopenline(M_device, speed, bmodemflag[MODEM_DIRECT]))
  686.       {
  687.  
  688.          hostp->hstatus =  nodevice;
  689.          return FALSE;
  690.       }
  691.  
  692.       while (sread(buf,1,0)); /* Discard trailing trash from modem
  693.                                  connect message                     */
  694.  
  695. /*--------------------------------------------------------------------*/
  696. /*                        Initialize the modem                        */
  697. /*--------------------------------------------------------------------*/
  698.  
  699.       if (!sendlist( initialize, modemTimeout, modemTimeout, noconnect))
  700.       {
  701.          printmsg(0,"dial: Modem failed to initialize");
  702.          shutDown();
  703.          hostp->hstatus =  dial_script_failed;
  704.          return FALSE;
  705.       }
  706.  
  707. /*--------------------------------------------------------------------*/
  708. /*           Setup the dial string and then dial the modem            */
  709. /*--------------------------------------------------------------------*/
  710.  
  711.       strcpy(buf, dialPrefix);
  712.       strcat(buf, number);
  713.       if (dialSuffix != NULL)
  714.          strcat(buf, dialSuffix);
  715.  
  716.       sendstr( buf );         /* Send the command to the telephone      */
  717.  
  718.       if (!sendlist(connect,  modemTimeout, dialTimeout, noconnect))
  719.       {
  720.          hostp->hstatus =  dial_failed;
  721.          return FALSE;
  722.       }
  723.  
  724.    }  /* if ( !IsNetwork() ) */
  725.  
  726.    printmsg(3, "dial: Modem reports connected");
  727.  
  728.    time( &remote_stats.lconnect );
  729.    remote_stats.calls ++ ;
  730.  
  731.    if ( !IsNetwork() )
  732.       autobaud(speed);     /* Reset modem speed, if desired          */
  733.  
  734.    setPrty(M_priority, M_prioritydelta );
  735.  
  736. /*--------------------------------------------------------------------*/
  737. /*                      Report success to caller                      */
  738. /*--------------------------------------------------------------------*/
  739.  
  740.    return TRUE;            /* Dial succeeded    */
  741.  
  742. } /* dial */
  743.  
  744. /*--------------------------------------------------------------------*/
  745. /*    a u t o b a u d                                                 */
  746. /*                                                                    */
  747. /*    autobaud a modem which has just connected                       */
  748. /*--------------------------------------------------------------------*/
  749.  
  750. static void autobaud( const BPS speed )
  751. {
  752.    char buf[10];
  753.  
  754.    ssleep(1);                 /*  Allow modem port to stablize       */
  755.  
  756.    if (bmodemflag[MODEM_CD])
  757.       CD();                   /* Set the carrier detect flags        */
  758.  
  759. /*--------------------------------------------------------------------*/
  760. /*                  Autobaud the modem if requested                   */
  761. /*--------------------------------------------------------------------*/
  762.  
  763.    if (!bmodemflag[MODEM_FIXEDSPEED])
  764.    {
  765.       size_t len = 0;
  766.  
  767.       memset( buf, '\0', sizeof( buf ));  /* Zero buffer                */
  768.       while ((len < sizeof buf) && sread( &buf[len],1,0))
  769.          len = strlen( buf );             /* Get speed into buffer      */
  770.  
  771.       if (len > 5)
  772.       {
  773.          char  *token;           /* Pointer to buffer value */
  774.          token = strtok(buf,WHITESPACE);
  775.          if (strlen(token))
  776.          {
  777.             BPS new_speed = (unsigned) atol(token);
  778.             if ((new_speed != speed) && (new_speed > 300))
  779.             {
  780.                printmsg(2, "autobaud: speed select %s", token);
  781.                SIOSpeed(new_speed);
  782.             } /* if */
  783.          } /* if */
  784.       } /* if */
  785.       else
  786.          printmsg(3, "autobaud: unable to speed select, using %d", speed);
  787.    } /* if */
  788.  
  789. } /* autobaud */
  790.  
  791. /*--------------------------------------------------------------------*/
  792. /*    s h u t d o w n                                                 */
  793. /*                                                                    */
  794. /*    Terminate modem processing via hangup                           */
  795. /*--------------------------------------------------------------------*/
  796.  
  797. void shutDown( void )
  798. {
  799.    static boolean recurse = FALSE;
  800.  
  801.    if ( ! portActive )          /* Allowed for Ctrl-Break           */
  802.       return;
  803.  
  804.    if ( !recurse )
  805.    {
  806.       boolean aborted = terminate_processing;
  807.       unsigned long saveRaised = raised;
  808.       recurse = TRUE;
  809.       terminate_processing = FALSE;
  810.       raised = 0;
  811.       hangup();
  812.       resetPrty();               // Drop out of hyperspace
  813.       sendlist( dropline, modemTimeout, modemTimeout, NULL);
  814.       recurse = FALSE;
  815.       terminate_processing |= aborted;
  816.       saveRaised |= raised;
  817.    }
  818.  
  819.    closeline();
  820.    norecovery = TRUE;
  821.  
  822. }  /* shutDown */
  823.  
  824. /*--------------------------------------------------------------------*/
  825. /*    s e n d l i s t                                                 */
  826. /*                                                                    */
  827. /*    Send a NULL terminated list of send/expect strings              */
  828. /*--------------------------------------------------------------------*/
  829.  
  830. static boolean sendlist(   char **list,
  831.                            int timeout,
  832.                            int lasttimeout,
  833.                            char **failure)
  834. {
  835.    boolean expect = TRUE;
  836.  
  837.    if (list == NULL)          /* Was the field supplied?             */
  838.       return TRUE;            /* No --> Must be optional, return     */
  839.  
  840. /*--------------------------------------------------------------------*/
  841. /*     Run through the list, alternating expect and send strings      */
  842. /*--------------------------------------------------------------------*/
  843.  
  844.    while( *list != NULL)
  845.    {
  846.  
  847.       if (expect)
  848.       {
  849.          char *exp = strdup( *list );
  850.          boolean success;
  851.          checkref( exp );
  852.          success = sendalt( exp,
  853.                             (*(++list) == NULL) ? lasttimeout : timeout,
  854.                             failure);
  855.          free( exp );
  856.          if (!success)
  857.             return FALSE;
  858.       }
  859.       else
  860.          sendstr( *list++ );
  861.       expect = ! expect;
  862.    } /* while */
  863.  
  864. /*--------------------------------------------------------------------*/
  865. /*    If we made it this far, success is at hand; return to caller    */
  866. /*--------------------------------------------------------------------*/
  867.  
  868.    return TRUE;
  869. } /* sendlist */
  870.  
  871. /*--------------------------------------------------------------------*/
  872. /*    s e n d a l t                                                   */
  873. /*                                                                    */
  874. /*    Expect a string, with alternates                                */
  875. /*--------------------------------------------------------------------*/
  876.  
  877. static boolean sendalt( char *exp, int timeout, char **failure)
  878. {
  879.    int ok;
  880.  
  881.    for ( ;; )
  882.    {
  883.       char *alternate = strchr(exp, '-');
  884.  
  885.       if (alternate != nil(char))
  886.          *alternate++ = '\0';
  887.  
  888.       ok = expectstr(exp, timeout, failure);
  889.  
  890.       if ( terminate_processing || raised )
  891.       {
  892.          shutDown();
  893.          return FALSE;
  894.       }
  895.  
  896.       if (ok || (alternate == nil(char)))
  897.          return (ok == 1);
  898.  
  899.       if (bmodemflag[MODEM_CD] && ! CD())
  900.       {
  901.          printmsg(0,"sendalt: Serial port reports modem not ready");
  902.          return FALSE;
  903.       }
  904.  
  905.       exp = strchr(alternate, '-');
  906.       if (exp != nil(char))
  907.          *exp++ = '\0';
  908.  
  909.       printmsg(0, "sending alternate");
  910.       sendstr(alternate);
  911.    } /*for*/
  912.  
  913. } /* sendalt */
  914.  
  915. /*--------------------------------------------------------------------*/
  916. /*    G e t G W i n d o w                                             */
  917. /*                                                                    */
  918. /*    Report the size of the allowed window for the "g" protocol      */
  919. /*--------------------------------------------------------------------*/
  920.  
  921. KEWSHORT GetGWindow(  KEWSHORT maxvalue , const char protocol )
  922. {
  923.    KEWSHORT ourWindowSize = 0;
  924.  
  925.    switch( protocol )
  926.    {
  927.       case 'g':
  928.          ourWindowSize = gWindowSize;
  929.          break;
  930.  
  931.       case 'G':
  932.          ourWindowSize = GWindowSize;
  933.          break;
  934.  
  935.       case 'v':
  936.          ourWindowSize = vWindowSize;
  937.          break;
  938.  
  939.       default:
  940.          printmsg(0,"GetGWindow: Invalid protocol %c",protocol);
  941.          panic();
  942.    }
  943.  
  944.    if ( (ourWindowSize < 1 ) || (ourWindowSize > maxvalue))
  945.       return maxvalue;
  946.    else
  947.       return ourWindowSize;
  948.  
  949. } /* GetGWindow */
  950.  
  951. /*--------------------------------------------------------------------*/
  952. /*    G e t G P a c k e t                                             */
  953. /*                                                                    */
  954. /*    Return the allowed packet size for the "g" procotol             */
  955. /*--------------------------------------------------------------------*/
  956.  
  957. KEWSHORT GetGPacket( KEWSHORT maxvalue , const char protocol)
  958. {
  959.    KEWSHORT savePacketSize ;
  960.    KEWSHORT ourPacketSize = 0;
  961.    int bits = 6;              /* Minimum Packet Size is 64 bytes     */
  962.  
  963.    switch( protocol )
  964.    {
  965.       case 'g':
  966.          ourPacketSize = gPacketSize;
  967.          break;
  968.  
  969.       case 'G':
  970.          ourPacketSize = GPacketSize;
  971.          break;
  972.  
  973.       case 'v':
  974.          ourPacketSize = vPacketSize;
  975.          break;
  976.  
  977.       default:
  978.          printmsg(0,"GetGPacket: Invalid protocol %c",protocol);
  979.          panic();
  980.    }
  981.  
  982.    savePacketSize = ourPacketSize;
  983.  
  984. /*--------------------------------------------------------------------*/
  985. /*                 Insure the value is a power of two                 */
  986. /*--------------------------------------------------------------------*/
  987.  
  988.    while( (ourPacketSize >> (bits+1)) > 0 )
  989.       bits++;
  990.  
  991.    ourPacketSize = (ourPacketSize >> bits) << bits;
  992.    if ( savePacketSize != ourPacketSize )
  993.       printmsg(0,"packetsize for %c protocol rounded down from %d to %d",
  994.                protocol,
  995.                (int) savePacketSize, (int) ourPacketSize );
  996.  
  997. /*--------------------------------------------------------------------*/
  998. /*    Return the smaller of the argument (the largest packet size     */
  999. /*    the packet driver supports) or what the modem file allows.      */
  1000. /*--------------------------------------------------------------------*/
  1001.  
  1002.    if ( (ourPacketSize < 1 ) || (ourPacketSize > maxvalue))
  1003.       return maxvalue;
  1004.    else
  1005.       return ourPacketSize;
  1006.  
  1007. } /* GetGPacket */
  1008.